package xin.yangshuai.forest01.service;

import com.dtflys.forest.config.ForestConfiguration;
import com.dtflys.forest.converter.json.ForestJsonConverter;
import com.dtflys.forest.exceptions.ForestNetworkException;
import com.dtflys.forest.exceptions.ForestRuntimeException;
import com.dtflys.forest.http.ForestCookie;
import com.dtflys.forest.http.ForestHeader;
import com.dtflys.forest.http.ForestRequest;
import com.dtflys.forest.http.ForestResponse;
import com.dtflys.forest.utils.TypeReference;
import org.springframework.stereotype.Component;
import xin.yangshuai.common01.entity.BaseResult;
import xin.yangshuai.common01.entity.Dept;
import xin.yangshuai.common01.entity.User;
import xin.yangshuai.forest01.client.MyClient;

import javax.annotation.Resource;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicReference;

@Component
public class MyService {

    @Resource(name = "config0")
    private ForestConfiguration config0;


    // 注入自定义的 Forest 接口实例
    @Resource
    private MyClient myClient;

    public void configInfo() {
        ForestJsonConverter jsonConverter = config0.getJsonConverter();
        System.out.println(jsonConverter);
    }

    public void testClient() {
        // 调用自定义的 Forest 接口方法
        // 等价于发送 HTTP 请求，请求地址和参数即为 helloForest 方法上注解所标识的内容
        String result = myClient.helloForest();
        // result 即为 HTTP 请求响应后返回的字符串类型数据
        System.out.println(result);
    }

    public String test() {

//        String result = myClient.simpleRequest();

        // 在调用该方法时通过参数传入 HTTP 请求方法类型（字符串类型，大小写不敏感）
//        String result = myClient.simpleRequest("POST");

//        String url = "http://localhost:28080/basic01/info";

//        String result = myClient.send4("info");

//        String result = myClient.sendData3();

//        String result = myClient.sendData();

        // 会对第二个参数 B&c=C 进行URL Encode
//        String result = myClient.send2("A", "B&c=C");

        // 会用参数输入的字符串替换URL中的 ${parameters} 部分
//        String result = myClient.send5("a=A&b=B&c=C");

//        String result = myClient.send("A","B");

//        Map<String, Object> map = new HashMap<>();
//        map.put("a","A");
//        map.put("b","B");

//        String result = myClient.send1(map);

//        List<Integer> list = new ArrayList<>();
//        list.add(1);
//        list.add(2);
//        list.add(3);

//        String result = myClient.send1(list);
//        String result = myClient.send(list);

//        String result = myClient.sendData("Foo", "Bar", req -> {
//            // req 为请求对象
//            System.out.println(req.queryString());
//            // 返回值将作为参数值添加到 URL Query 中
//
//            String encode = Base64.encode(req.queryString().getBytes());
//
//            return encode;
//        });

//        String result = myClient.multipleHeaders();

//        String result = myClient.bindingHeader("gbk");

//        String result = myClient.bindingHeader1("Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6)");

//        String result = myClient.postUser("*/*", "token");

//        Map<String, Object> map = new HashMap<>();
//        map.put("User-Agent", "A");
//        map.put("Content-Type", "text/plain");
//
//        String result = myClient.headHelloUser(map);

//        String result = myClient.sendData1("Foo", "Bar", req -> {
//            // req 为请求对象
//            // 返回值将作为参数值添加到请求头中
//            String encode = Base64.encode(req.queryString().getBytes());
//
//            return encode;
//        });

//        String result = myClient.sendPost("zhangsan", "123456");

//        String result = myClient.helloUser("zhangsan", "123456");

//        List<String> list = new ArrayList<>();
//        list.add("A");
//        list.add("B");
//        list.add("C");
//        String result = myClient.helloUserNames(list);

        Map<String, Object> map = new HashMap<>();
        map.put("name", "foo");
        map.put("password", "bar");
//        String result = myClient.helloUser(map);
//        String result = myClient.helloUser1(map);
        String result = myClient.helloUser2("okhttp3", map);

        return result;
    }

    public User test1() {
//        Map<String, Object> map = new HashMap<>();
//        map.put("name", "foo");
//        map.put("password", "bar");
//
//        User user = myClient.helloUser4(map);

        User user1 = new User();
        user1.setId("002");
        user1.setName("lisi");
        user1.setAge(20);
        user1.setBirthday(new Date());
        User user = myClient.helloUser3(user1);

        return user;
    }

    public String test2() {
        Map<String, Object> map = new HashMap<>();
        map.put("name", "foo");
        map.put("password", "bar");

        // 如果请求方法以 ForestRequest 作为返回值类型
        // 不会直接发送请求
        // 而是直接返回 Forest 请求对象
        ForestRequest<?> request = myClient.getForestRequest(map);
        String path = request.path(); // 得到字符串 /test
        System.out.println(path);
        System.out.println(request.getURI());
        System.out.println(request.getUrl());
        System.out.println(request.getBody());
        // 手动执行发送请求，并以字符串形式接受响应数据
        String ret = request.execute(String.class);
        User user = request.execute(User.class);

        return ret;
    }

    public String test3() {
        Map<String, Object> map = new HashMap<>();
        map.put("name", "foo");
        map.put("password", "bar");

        // 以ForestResponse类型变量接受响应数据
        ForestResponse<String> response = myClient.postUser(map);

        // 用isError方法去判断请求是否失败
        if (response.isError()) {
            System.out.println("isError");
        }

        // 用isSuccess方法去判断请求是否成功
        if (response.isSuccess()) {
            System.out.println("isSuccess");
        }

        // 以字符串方式读取请求响应内容
        String text = response.readAsString();

        // getContent方法可以获取请求响应内容文本
        // 和readAsString方法不同的地方在于，getContent方法不会读取二进制形式数据内容，
        // 而readAsString方法会将二进制数据转换成字符串读取
        String content = response.getContent();

        // 获取反序列化成对象类型的请求响应内容
        // 因为返回类型为ForetReponse<String>, 其泛型参数为String
        // 所以这里也用String类型获取结果
        String result = response.getResult();

        // 以字节数组的形式获取请求响应内容
//        byte[] byteArray = response.getByteArray();

        // 以输入流的形式获取请求响应内容
//        InputStream in = response.getInputStream();


        ForestResponse<User> response1 = myClient.postUser1(map);
        // 判断请求是否成功
        if (response1.isSuccess()) {

            // 根据响应头名称获取单个请求响应头
            ForestHeader header = response.getHeader("Content-Type");
            // 响应头名称
            String headerName = header.getName();
            // 响应头值
            String headerValue = header.getValue();

            // 根据响应头名称获取请求响应头列表
            List<ForestHeader> heaers = response.getHeaders("Content-Type");

            // 根据响应头名称获取请求响应头值
            String val = response.getHeaderValue("Content-Type");

            // 根据响应头名称获取请求响应头值列表
            List<String> vals = response.getHeaderValues("Content-Type");

            // 通过getResult方法获取其响应内容反序列化后的结果
            // 因为返回类型 ForestResponse<User> 中泛型参数为 User,
            // 所以得到反序列化后的对象也是User类型对象
            User user = response1.getResult();
            System.out.println(user);
        }


        return result;
    }

    // 重试
    public String test4() {
        Map<String, Object> map = new HashMap<>();
        map.put("name", "foo");
        map.put("password", "bar");

//        String result = myClient.postUser2(map);

        ForestResponse<String> response = myClient.postUser3(map);

        if (response.isSuccess()) {
            System.out.println("isSuccess");
        }

        if (response.isError()) {
            System.out.println("isError");
        }

        String result = response.readAsString();

        return result;
    }

    // 回调
    public String test5() {
        Map<String, Object> map = new HashMap<>();
        map.put("name", "foo");
        map.put("password", "bar");

        String result = myClient.postUser4(map, (String resText, ForestRequest request, ForestResponse response) -> {
                    // 成功响应回调
                    System.out.println(resText);
                },
                (ForestRuntimeException ex, ForestRequest request, ForestResponse response) -> {
                    // 异常回调
                    System.out.println(ex.getMessage());
                });

        return result;
    }

    // 异步
    public String test6() {
        Map<String, Object> map = new HashMap<>();
        map.put("name", "foo");
        map.put("password", "bar");

        myClient.asyncGet(map, (String resText, ForestRequest request, ForestResponse response) -> {
                    // 成功响应回调
                    System.out.println("异步：" + resText);
                },
                (ForestRuntimeException ex, ForestRequest request, ForestResponse response) -> {
                    // 异常回调
                    System.out.println("异步：" + ex.getMessage());
                });

        return "hello";
    }

    // cookie
    public String test7() {
        Map<String, Object> map = new HashMap<>();
        map.put("name", "foo");
        map.put("password", "bar");

        AtomicReference<ForestCookie> cookieAtomic = new AtomicReference<>(null);

        // 调用登入接口
        myClient.testLogin(map, (request, cookies) -> {
            // 将服务端传来的Cookie放入cookieAtomic
            cookieAtomic.set(cookies.allCookies().get(0));

            ForestCookie forestCookie = cookies.allCookies().get(0);
            System.out.println(forestCookie);
        });

        // 获取Cookie
        ForestCookie cookie = cookieAtomic.get();

        // 调用登入后的测试接口
        ForestResponse response = myClient.testAfterLogin((request, cookies) -> {
            // 将之前调用登入接口获得的Cookie传入请求发送到服务端
            cookies.addCookie(cookie);
            ForestCookie forestCookie = new ForestCookie("hello", "123456");
            cookies.addCookie(forestCookie);
        });

        return "hello";
    }

    // 异常
    public String test8() {
        Map<String, Object> map = new HashMap<>();
        map.put("name", "foo");
        map.put("password", "bar");

        /**
         * try-catch方式：捕获ForestNetworkException异常类的对象
         */
        try {
            String result = myClient.postUser5(map);
            return result;
        } catch (ForestNetworkException ex) {
            int status = ex.getStatusCode(); // 获取请求响应状态码
            ForestResponse<String> response = ex.getResponse(); // 获取Response对象
            String content = response.getContent(); // 获取请求的响应内容
            String resResult = response.getResult(); // 获取方法返回类型对应的最终数据结果

            System.out.println(status);
            System.out.println(content);
            System.out.println(resResult);
        }

        return "hello";
    }

    // 拦截器
    public String test9() {
        Map<String, Object> map = new HashMap<>();
        map.put("name", "foo");
        map.put("password", "bar");
        map.put("age", 22);
        map.put("birthday", new Date());

        User user1 = new User();
        user1.setId("002");
        user1.setName("lisi");
        user1.setAge(20);
        user1.setBirthday(new Date());

        /**
         * try-catch方式：捕获ForestNetworkException异常类的对象
         */
        try {
            String result = myClient.postUser6(map);

            String result1 = myClient.postUser9(user1);

            String result2 = myClient.getUser1(user1);

            return result;
        } catch (ForestNetworkException ex) {
            int status = ex.getStatusCode(); // 获取请求响应状态码
            ForestResponse<String> response = ex.getResponse(); // 获取Response对象
            String content = response.getContent(); // 获取请求的响应内容
            String resResult = response.getResult(); // 获取方法返回类型对应的最终数据结果

            System.out.println(status);
            System.out.println(content);
            System.out.println(resResult);
        }

        return "hello";
    }

    // 泛型
    public String test10() {
        Map<String, Object> map = new HashMap<>();
        map.put("name", "foo");
        map.put("password", "bar");


        ForestRequest<?> request = myClient.postUser7(map);
        // 手动执行发送请求，并以字符串形式接受响应数据
        String result = request.execute(String.class);

        BaseResult<User> userBaseResult = request.execute(new TypeReference<BaseResult<User>>() {
        });

        BaseResult<User> userBaseResult1 = myClient.postUser8(map);

        return "hello";
    }

    // 复杂参数
    public String test11() {

        Map<String, Object> map1 = new HashMap<>();
        map1.put("name", "foo");
        map1.put("password", "bar");

        Map<String, Object> map = new HashMap<>();
        map.put("name", "foo");
        map.put("password", "bar");
        map.put("info", map1);

        ForestRequest<?> request = myClient.postUser10(map);
        // 手动执行发送请求，并以字符串形式接受响应数据
        String result = request.execute(String.class);

        User user1 = new User();
        user1.setId("002");
        user1.setName("lisi");
        user1.setAge(20);
        user1.setBirthday(new Date());

        Dept dept = new Dept();
        dept.setName("dept01");
        dept.setUser(user1);

        ForestRequest<?> request1 = myClient.postUser11(dept);
        // 手动执行发送请求，并以字符串形式接受响应数据
        String result1 = request1.execute(String.class);


        return "hello";
    }

}
